﻿namespace ScrumLite.Data.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Transactions;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Summary description for ReviewStoreFixture
    /// </summary>
    [TestClass]
    public class ReviewStoreFixture
    {
        IReviewStore store;
        static Guid projectId = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434B5A");
        static DateTime date1 = new DateTime(2008, 1, 1);

        static Guid r1Id = new Guid("1F4F9968-8D5E-4d8a-9BD8-9A8DF1434B5A");

        [TestInitialize]
        public void Initialize()
        {
            this.store = new ReviewStore();
        }

        [TestMethod()]
        public void ShouldReturnZeroReviewsForANotExistingProject()
        {
            IList<Review> reviews = this.store.RetrieveReviews(Guid.NewGuid());

            Assert.AreEqual(0, reviews.Count);
        }

        [TestMethod()]
        public void ShouldRetrieveDailyReviewCount()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeReviewStore();
       
                Dictionary<DateTime, int> dailies = this.store.RetrieveDailyReviewCount(projectId);
                Assert.AreEqual(1,dailies.Keys.Count);

                foreach (var k in dailies.Keys)
                {
                    Assert.IsTrue(dailies[k] > 0);
                    Assert.AreEqual(date1, k);
                }
            }
        }

        [TestMethod()]
        public void ShouldReturnReviewsOrderedByWhenOnDescending()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Guid projectId = MockHelpers.KnownProjectId;

                this.store.Add(new Review() { id = Guid.NewGuid(), fk_project = projectId, conductedBy = "John", occuredOn = DateTime.Now, uri_evidence = "http://some url"});
                this.store.Add(new Review() { id = Guid.NewGuid(), fk_project = projectId, conductedBy = "John", occuredOn = DateTime.Now.Subtract(TimeSpan.FromDays(1)), uri_evidence = "http://some url" });
                this.store.Add(new Review() { id = Guid.NewGuid(), fk_project = projectId, conductedBy = "John", occuredOn = DateTime.Now.Subtract(TimeSpan.FromDays(2)), uri_evidence = "http://some url" });

                IList<Review> reviews = this.store.RetrieveReviews(projectId);
                Assert.AreEqual(3, reviews.Count);
                Assert.IsTrue(reviews[0].occuredOn > reviews[1].occuredOn);
                Assert.IsTrue(reviews[1].occuredOn > reviews[2].occuredOn);
            }
        }

        [TestMethod]
        public void ShouldAddReview()
        {
            using (TransactionScope scope = new TransactionScope())
            {                
                Review review = new Review()
                {
                    id = Guid.NewGuid(),
                    fk_project = MockHelpers.KnownProjectId,
                    conductedBy = "John",
                    occuredOn = DateTime.Now,
                    uri_evidence = "http://some url"
                };

                this.store.Add(review);

                Review actual = this.store.RetrieveReview(review.id);

                Assert.AreEqual(review.id, actual.id);
                Assert.AreEqual(review.fk_project, actual.fk_project);
                Assert.AreEqual(review.conductedBy, actual.conductedBy);
                Assert.AreEqual(review.occuredOn.Date, actual.occuredOn.Date);
                Assert.AreEqual(review.uri_evidence, actual.uri_evidence);
            }
        }

        [TestMethod]
        public void ShouldUpdateReview()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Review review = new Review()
                {
                    id = Guid.NewGuid(),
                    fk_project = MockHelpers.KnownProjectId,
                    conductedBy = "Auditor",
                    occuredOn = DateTime.Now,
                    uri_evidence = "http://some url"
                };

                this.store.Add(review);

                review.conductedBy = "Auditor updated";
                review.occuredOn = DateTime.Now.Subtract(TimeSpan.FromDays(1));
                review.uri_evidence = "http://some url_updated";

                store.Update(review);

                Review actual = store.RetrieveReview(review.id);

                Assert.AreEqual(review.conductedBy, actual.conductedBy);
                Assert.AreEqual(review.occuredOn.Date, actual.occuredOn.Date);
                Assert.AreEqual(review.uri_evidence, actual.uri_evidence);
            }
        }

        private static void CreateFakeReviewStore()
        {
            using (ScrumLiteDataContext context = new ScrumLiteDataContext())
            {
                Project project = new Project() { endsOn = DateTime.Today, id = projectId, name = "FakeProject", security_group = "", startsOn = DateTime.Today, uri_repository = "", user_ownedBy = "" };
                context.Projects.InsertOnSubmit(project);

                Review review = new Review() { id = r1Id, fk_project = projectId, conductedBy = "Guest", occuredOn = date1, uri_evidence = "http://tempuri.org/guest" };
                context.Reviews.InsertOnSubmit(review);

                context.SubmitChanges();
            }
        }
    }
}
